package com.ruoyi.aitcommon.utils;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.ruoyi.aitcommon.function.BiFunctionEx;

/**
 * 封装FastJSON
 * @author Administrator
 *
 */
public class JSONUtils {
////	通过正则表达式去掉备注
//	@Deprecated
//	private static String removeComment(String jsonstr) {
//		/**
//		 * 正则表达式匹配注释，分为两部分：
//		 * 1、// 注释,该注释已//开头(排除 ://)，中间包含.*，" or } or { or ] or 文件结束 为结束且不包含 结束符号
//		 * 2、/*  \*\/ 注释，该注释 /*开头，中间包含(\\s|.)*?，以\*\/为结束
//		 */
//		String pattern="(?<!\\:)\\/\\/.*?(?=\"|\\}|\\{|\\]|$)|\\/\\*(\\s|.)*?\\*\\/";
//
//		Pattern compile = Pattern.compile(pattern);
//		Matcher matcher = compile.matcher(jsonstr);
//		String retstr = matcher.replaceAll("");
//		return retstr;
//	}

////	通过正则表达式去掉备注
//	@Deprecated
//	private static String removeCommentWithCR(String jsonstr) {
//		/**
//		 * 正则表达式匹配注释，分为两部分：
//		 * 1、// 注释,该注释以//开头(排除 ://)，\r\n 结束
//		 * 2、/*  \*\/ 注释，该注释 /*开头，中间包含(\\s|.)*?，以\*\/为结束
//		 * 这个正则表达式还是有BUG,如果是字符串里面的//也会认为是注释
//		 */
//		String pattern="(?<!\\:)\\/\\/.*?(?=\\r|\\n)|\\/\\*(\\s|.)*?\\*\\/";
//
//		Pattern compile = Pattern.compile(pattern);
//		Matcher matcher = compile.matcher(jsonstr);
//		String retstr = matcher.replaceAll("");
//		return retstr;
//	}

//	JOSNObject.parseObject(str,Feature.AllowComment)不起作用
//	增加对备注的支持
//	这里没有回车符,通过其他字符解析备注

	/**
	 * 在JSONArray中查找匹配记录
	 * @param array
	 * @param field 匹配字段名
	 * @param value 匹配值
	 * @return JSONObject
	 */
	public static JSONObject FindJSONArray(JSONArray array,String field,String value) throws Exception {
		final int index = FindJSONArrayIndex(array, field, value);
		if(index==-1){
			return null;
		}else{
			return array.getJSONObject(index);
		}
	}

	public static int FindJSONArrayIndex(JSONArray array,String field,String value) throws Exception {
		for(int i=0;i<array.size();i++){
			JSONObject jsonObject = array.getJSONObject(i);
			if(!jsonObject.containsKey(field)){
				ExceptionUtils.throwException(null, "字段[{}]不存在!", field);
			}
			final String key = value;
			final String key1 = jsonObject.getString(field);
			if(key.equals(key1)){
				//记录匹配到
				return i;
			}
		}
		return -1;
	}

	/**
	 * JSONArray转换为List
	 * @param array
	 * @param field 集合中字段名,可以为空
	 * @return ArrayList<String>
	 */
	public static List<String> JSONArrayToList(JSONArray array,String field) throws Exception {
		List<String> ret = new ArrayList<>();
		for(int i=0;i<array.size();i++){
			if(ObjUtils.isBlank(field)){
				ret.add(array.getString(i));
			}else{
				JSONObject jsonObject = array.getJSONObject(i);
				if (!jsonObject.containsKey(field)){
					ExceptionUtils.throwException(null,"字段%s不存在",field);
				}
				// 将字段的值加入到 list 中
				ret.add(jsonObject.getString(field));
			}
		}
		return ret;
	}

	/**
	 * 将对象转换为JSONObject
	 * @param obj
	 * @return
	 */
	public static JSONObject toJSON(Object obj){
		return (JSONObject) JSONObject.toJSON(obj);
	}

	/**
	 * 传入对象可能是JSONObject或JSONArray
	 * 返回JSONObject或JSONArray的第一条
	 * @param obj
	 * @return
	 */
	public static JSONObject getJSONObjectByObject(Object obj) throws Exception {
		JSONObject ret=null;
		if(obj instanceof JSONObject)
			ret=(JSONObject)obj;
		else if (obj instanceof JSONArray){
			JSONArray  array=(JSONArray)obj;
			ExceptionUtils.checkBlankOrUndefined(array, "传入JSONArray为空");
			ret=(JSONObject) array.get(0);
		}
		else
			throw new Exception("传入参数不是JSONObject或JSONArray");
		return ret;
	}
	/**
	 * JSON对象翻译
	 * @param params 为了兼容老代码,传入类型为Map
	 * @param action
	 * @return 转换后的JSON对象
	 */
	private static JSONObject pathJSONObject(Map<String,Object> params,BiFunctionEx<String,Object,Object[]> action) throws Exception {
		JSONObject ret=new JSONObject();
		for(String key:params.keySet()){
			Object val=params.get(key);
			if(val instanceof Map){
				final JSONObject retJSON = pathJSONObject((Map) val, action);
				ret.put(key,retJSON);
			}else if(val instanceof List){
				final JSONArray retArray = pathJSONArray((List) val, action);
				ret.put(key,retArray);
			}else{
				Object[] rets = action.apply(key, val);
				ret.put(rets[0].toString(),rets[1]);
			}
		}
		return ret;
	}

	/**
	 * JSON集合翻译
	 * @param params 为了兼容老代码,传入类型为List
	 * @param action
	 * @return JSON集合
	 */
	private static JSONArray pathJSONArray(List<Object> params,BiFunctionEx<String,Object,Object[]> action) throws Exception {
		JSONArray ret=new JSONArray();
		for (Object param : params) {
			if(param instanceof Map){
				final JSONObject jsonObject = pathJSONObject((Map) param, action);
				ret.add(jsonObject);
			}else if(param instanceof List){
				final JSONArray objects = pathJSONArray((List) param, action);
				ret.add(objects);
			}else{
//				值为其他对象,直接处理
				Object[] rets = action.apply(null, param);
				ret.add(rets[1]);
			}
		}
		return ret;
	}

	/**
	 * 递归循环Object(JSONObject/JSONArray)中的所有key(包含子JSON),调用lamda函数处理,并返回构造的新Object
	 * @param params JSONObject/JSONArray,兼容老代码传入的Map/List
	 * @param action 处理lamda函数
	 * @return 处理后的JSONObject/JSONArray
	 */
	public static Object pathJSON(Object params, BiFunctionEx<String,Object,Object[]> action) throws Exception {
//		构造的新Object
		Object retObj;
		if(params instanceof Map){
			retObj = pathJSONObject((Map) params, action);
		}else if(params instanceof JSONArray){
			retObj = pathJSONArray((JSONArray) params,action);
		}else{
//			值为其他对象,直接处理
			Object[] rets = action.apply(null, params);
			retObj=rets[1];
		}

		return retObj;
	}

	/**
	 * 将字符串转换为JSONObject
	 * @param jsonstr JSON字符串
	 * @return JSONObject
	 */
	public static JSONObject parseObject(String jsonstr) {
//		String str=removeComment(jsonstr);
//		重新使用Feature.AllowComment处理注释,不再自己处理
		return JSONObject.parseObject(jsonstr,Feature.AllowComment,Feature.OrderedField);
	}

	public static <T> T toJavaObject(String jsonstr,Class<T> clazz) {
//		String str=removeComment(jsonstr);
//		重新使用Feature.AllowComment处理注释,不再自己处理
		JSONObject json=parseObject(jsonstr);
		final T obj = JSONObject.toJavaObject(json, clazz);
		return obj;
	}

	/**
	 * 将字符串转换为JSONObject或JSONArray
	 *
	 * JSON.parse() 方法：
	 * JSON.parse() 方法会将 JSON 字符串解析为一个 Object 类型的对象。
	 * 如果 JSON 是一个对象（用 {} 包裹），则返回的是 JSONObject。
	 * 如果 JSON 是一个数组（用 [] 包裹），则返回的是 JSONArray。
	 * instanceof 判断：
	 * 使用 instanceof 关键字可以判断解析后的对象是 JSONObject 还是 JSONArray。
	 * 根据判断结果进行相应的处理。
	 * 类型转换：
	 * 如果确认是 JSONObject 或 JSONArray，可以将其强制转换为对应的类型，并调用相关的方法。
	 *
	 * @param jsonstr JSON字符串
	 * @return JSONObject或JSONArray
	 */
	public static Object parseJSON(String jsonstr){
		final Object json = JSON.parse(jsonstr,Feature.AllowComment,Feature.OrderedField);
		return json;
	}
	
	/**
	 * 读取JAVA包里面的JSON文件,去掉备注,转化为JSONObject对象
	 * 这里从文件加载,存在\r\n,按照回车符解析备注
	 * 该方法只在ymyy项目使用,过期
	 * @param pathfile 文件路径
	 * @return JSON对象
	 */
	@Deprecated
	public static JSONObject parseObjectFromResource(String pathfile) throws Exception {
		String filetext = FileUtils.getResourceFile(pathfile);
//		String str=removeCommentWithCR(filetext);
//		重新使用Feature.AllowComment处理注释,不再自己处理
		return JSONObject.parseObject(filetext,Feature.AllowComment);
	}

	/**
	 * 校验JSON格式是否JSONObject
	 * @param jsonstr JSON字符串
	 * @return 是否正确
	 */
	public static boolean validJSONObjectStr(String jsonstr) {
		try {
			if(ObjUtils.isBlank(jsonstr)) return true;
//			重新使用Feature.AllowComment处理注释,不再自己处理
			JSONObject.parseObject(jsonstr,Feature.AllowComment);
		}catch(Exception ex) {
			return false;
		}
		return true;
	}

	/**
	 * 校验JSON格式是否JSONObject或JSONArray
	 * @param jsonstr
	 * @return 格式是否正确
	 */
	public static boolean validJSONStr(String jsonstr) {
		try {
			if(ObjUtils.isBlank(jsonstr)) return true;
//			重新使用Feature.AllowComment处理注释,不再自己处理
			JSON.parseObject(jsonstr,Feature.AllowComment);
		}catch(Exception ex) {
			return false;
		}
		return true;
	}
}
